home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Application / Application.cp < prev    next >
Encoding:
Text File  |  1996-02-19  |  14.2 KB  |  500 lines  |  [TEXT/CWIE]

  1.  
  2. #include "Application.h"
  3. #include "AbstractDocument.h"
  4. #include "ScriptableDBDocument.h"
  5. #include "ResolveObjectSpecifier.h"
  6. #include "FileIterators.h"
  7. #include "MoreStrings.h"
  8.  
  9. #include <AppleEvents.h>
  10. #include <AERegistry.h>
  11. #include <ASRegistry.h>
  12. #include <TextUtils.h>
  13.  
  14. #include "Exceptions.h"
  15.  
  16. TPropertyDescription TApplication::fPropertiesOfClass[] = {
  17.     // "color" is temporary for resolution mode
  18.     {    pColor,                    0,        typeLongInteger,            typeLongInteger            },
  19.     {    pSelection,                0,        typeAEList,                    typeObjectSpecifier        },
  20.     {    pIsFrontProcess,        0,        typeBoolean,                typeBoolean                },
  21.     {    pClipboard,                0,        typeObjectSpecifier,        typeObjectSpecifier        },
  22.     {    pInsertionLoc,            0,        typeObjectSpecifier,        typeObjectSpecifier        }
  23. };
  24.  
  25. #pragma segment ObjectResident
  26. ImplementClassData(TApplication, clApplication);
  27.  
  28. TApplication* TApplication::gApplication = nil;
  29.  
  30. //--------------------------------------------------------------------------------
  31. // TApplication::TApplication
  32. //--------------------------------------------------------------------------------
  33. TApplication::TApplication() :
  34.     fCloseRequestsPending(false),
  35.     fResolutionMode(3)
  36. {
  37.     //
  38.     // Remember our PSN and application FileSpec
  39.     //
  40.     GetCurrentProcess(&fPSN);
  41.     fFileSpec = TFSSpecification(fPSN);
  42. } // TApplication::TApplication
  43.  
  44. //--------------------------------------------------------------------------------
  45. // TApplication::ObjectClass
  46. //--------------------------------------------------------------------------------
  47. DescType TApplication::ObjectClass(const TAETransaction&, Boolean /*recordedClass*/)
  48. {
  49.     return cApplication;
  50. }
  51.  
  52. //--------------------------------------------------------------------------------
  53. // TApplication::DerivedFromOSLClass
  54. //--------------------------------------------------------------------------------
  55. Boolean TApplication::DerivedFromOSLClass(const TAETransaction& t, DescType objectClass)
  56. {
  57.     return ((objectClass == cApplication) || Inherited::DerivedFromOSLClass(t, objectClass));
  58. }
  59.  
  60. class TNullContainerIterator : public TAbstractObjectIterator
  61. {
  62. public:
  63.     TNullContainerIterator() {};
  64.     virtual ~TNullContainerIterator();
  65.  
  66.     virtual void                        Reset(const TAETransaction&, Boolean iterationDirection = kForwardIteration);
  67.     virtual Boolean                        More(const TAETransaction&) const;
  68.     virtual void                        Next(const TAETransaction&);
  69.  
  70.     virtual TAbstractScriptableObject*    Current(const TAETransaction&);
  71.     virtual void                        RemoveCurrent(const TAETransaction& t);
  72.  
  73.     virtual TAbstractScriptableObject*    GetNamedElement(const TAETransaction& t, DescType desiredClass, TDescriptor nameDesc);
  74.  
  75. private:
  76.     TDocumentLoop                        fDocumentIter;
  77. };
  78.  
  79. TNullContainerIterator::~TNullContainerIterator()
  80. {
  81. }
  82.  
  83. void TNullContainerIterator::Reset(const TAETransaction& t, Boolean iterationDirection /*= kForwardIteration*/)
  84. {
  85.     fDocumentIter.Reset(t, iterationDirection);
  86. }
  87.  
  88. Boolean TNullContainerIterator::More(const TAETransaction& t) const
  89. {
  90.     return fDocumentIter.More(t);
  91. }
  92.  
  93. void TNullContainerIterator::Next(const TAETransaction& t)
  94. {
  95.     fDocumentIter.Next(t);
  96. }
  97.  
  98. TAbstractScriptableObject* TNullContainerIterator::Current(const TAETransaction& t)
  99. {
  100.     return fDocumentIter.Current(t);
  101. }
  102.  
  103. void TNullContainerIterator::RemoveCurrent(const TAETransaction& t)
  104. {
  105.     fDocumentIter.RemoveCurrent(t);
  106. }
  107.  
  108. TAbstractScriptableObject* TNullContainerIterator::GetNamedElement(const TAETransaction& t, DescType desiredClass, TDescriptor nameDesc)
  109. {
  110.     TAbstractScriptableObject* result = nil;
  111.     
  112.     //
  113.     // First, check to see if the nameDesc is an int64; if so,
  114.     // don't quibble over "document id int64" vs "document int64",
  115.     // just return the appropriate document.
  116.     //
  117.     if(nameDesc.DescriptorType() == 'in64')
  118.     {
  119.         result = TApplication::Instance()->AccessByUniqueID(t, desiredClass, nameDesc);
  120.     }
  121.     else
  122.     {
  123.         result = fDocumentIter.GetNamedElement(t, desiredClass, nameDesc);
  124.     }
  125.     
  126.     //
  127.     // If we couldn't find an open document with the given name, then
  128.     // search the disk (that contains the running application) for
  129.     // a document with the given name
  130.     //
  131.     if(result == nil)
  132.     {
  133.         TStackBasedString fileName = nameDesc;
  134.  
  135.         for(TCatalogSearchIterator iter(TApplication::Instance()->AppFileVRefNum(), fileName, 'db  ', 'db++', kSeachFilesOnly | kNameMustMatchExactly | kOnlyOneMatch); iter.More(); iter.Next())
  136.         {
  137.             result = TScriptableDBDocument::OpenDatabase(iter.Current());
  138.         }
  139.     }
  140.     
  141.     return result;
  142. }
  143.  
  144. //--------------------------------------------------------------------------------
  145. // TApplication::ElementIterator
  146. //--------------------------------------------------------------------------------
  147. TAbstractObjectIterator* TApplication::ElementIterator(const TAETransaction&)
  148. {
  149.     // return new TDocumentLoop();
  150.     return new TNullContainerIterator();
  151. }
  152.  
  153. //--------------------------------------------------------------------------------
  154. // TApplication::Idle
  155. //
  156. // Called once per waitnextevent
  157. //--------------------------------------------------------------------------------
  158. void TApplication::Idle()
  159. {
  160.     if(fCloseRequestsPending)
  161.         this->ProcessCloseRequest();
  162. }
  163.  
  164. //--------------------------------------------------------------------------------
  165. // TApplication::TearDownApplication
  166. //--------------------------------------------------------------------------------
  167. void TApplication::TearDownApplication()
  168. {
  169.     //
  170.     // Close all open documents (documents should save themselves before closing)
  171.     //
  172.     for(TDocumentLoop iter; iter.More(TAETransaction()); iter.Next(TAETransaction()))
  173.     {
  174.         TAbstractDocument* doc = iter.RemoveCurrentDocument(TAETransaction());
  175.         delete doc;
  176.     }
  177. } // TApplication::TearDownApplication
  178.  
  179. //--------------------------------------------------------------------------------
  180. // TApplication::MarkForClose
  181. //--------------------------------------------------------------------------------
  182. void TApplication::MarkForClose(TAbstractDocument* doc)
  183. {
  184.     fCloseRequestsPending = true;
  185.     doc->MarkForClose();
  186. } // TApplication::MarkForClose
  187.  
  188. //--------------------------------------------------------------------------------
  189. // TApplication::ProcessCloseRequest
  190. //--------------------------------------------------------------------------------
  191. void TApplication::ProcessCloseRequest()
  192. {
  193.     Boolean requestsPending = false;
  194.     
  195.     if(fCloseRequestsPending)
  196.     {
  197.         for(TDocumentLoop iter; iter.More(TAETransaction()); iter.Next(TAETransaction()))
  198.         {
  199.             if(iter.CurrentDocument()->CloseRequested())
  200.             {
  201.                 //
  202.                 // Also test to see if doc can be closed
  203.                 // (wouldn't want to close a document that
  204.                 // some thread was working with)
  205.                 // 
  206.                 if(true)
  207.                 {
  208.                     TAbstractDocument* doc = iter.RemoveCurrentDocument(TAETransaction());
  209.                     delete doc;
  210.                 }
  211.                 else
  212.                     requestsPending = true;
  213.             }
  214.         }
  215.         fCloseRequestsPending = requestsPending;
  216.     }
  217. } // TApplication::ProcessCloseRequest
  218.  
  219. //--------------------------------------------------------------------------------
  220. // TApplication::FindDocument
  221. //--------------------------------------------------------------------------------
  222. TAbstractDocument* TApplication::FindDocument(Int64 documentID, Boolean searchForAndOpen /* = false */)
  223. {
  224.     TAbstractDocument* doc = nil;
  225.     
  226.     for(TDocumentLoop iter; iter.More(TAETransaction()); iter.Next(TAETransaction()))
  227.     {
  228.         if(iter.CurrentDocument()->DocumentIdentifier() == documentID)
  229.         {
  230.             doc = iter.CurrentDocument();
  231.             break;
  232.         }
  233.     }
  234.     
  235.     if((doc == nil) && (searchForAndOpen == true))
  236.     {
  237.         //
  238.         // Look for a document somewhere in our search path
  239.         // that has the given unique ID
  240.         //
  241.         // In the future, it would be a very good idea to cache
  242.         // the FSSpec and document ID of databases that we have
  243.         // seen, and look for entries in the cache before searching
  244.         // the entire disk.  For now we always search the disk,
  245.         // though.
  246.         //
  247.         for(TCatalogSearchIterator iter(TApplication::Instance()->AppFileVRefNum(), nil, 'db  ', 'db++', kSeachFilesOnly); iter.More(); iter.Next())
  248.         {
  249.             doc = TScriptableDBDocument::OpenDatabase(iter.Current(), documentID);
  250.             if(doc != nil)
  251.                 break;
  252.         }
  253.     }
  254.     
  255.     return doc;
  256. }
  257.  
  258. //--------------------------------------------------------------------------------
  259. // TApplication::FindDocument
  260. //--------------------------------------------------------------------------------
  261. TAbstractDocument* TApplication::FindDocument(TFSSpecification& fileSpec, Boolean openDocument /*= false*/)
  262. {
  263.     TAbstractDocument* doc = nil;
  264.     
  265.     for(TDocumentLoop iter; iter.More(TAETransaction()); iter.Next(TAETransaction()))
  266.     {
  267.         TFSSpecification currentFSSpec;
  268.         
  269.         if(iter.CurrentDocument()->DocumentFSSpecification(currentFSSpec) == true)
  270.         {
  271.             if(fileSpec == currentFSSpec)
  272.             {
  273.                 doc = iter.CurrentDocument();
  274.                 break;
  275.             }
  276.         }
  277.     }
  278.     
  279.     if((doc == nil) && (openDocument == true))
  280.         doc = TScriptableDBDocument::OpenDatabase(fileSpec);
  281.  
  282.     return doc;
  283. }
  284.  
  285. //--------------------------------------------------------------------------------
  286. // TApplication::DocumentIndex
  287. //--------------------------------------------------------------------------------
  288. long TApplication::DocumentIndex(Int64 documentID)
  289. {
  290.     long docIndex = 0;
  291.     Boolean found = false;
  292.     
  293.     for(TDocumentLoop iter; iter.More(TAETransaction()); iter.Next(TAETransaction()))
  294.     {
  295.         ++docIndex;
  296.         
  297.         if(iter.CurrentDocument()->DocumentIdentifier() == documentID)
  298.         {
  299.             found = true;
  300.             break;
  301.         }
  302.     }
  303.     
  304.     if(found == false)
  305.         FailErr(errAENoSuchObject);
  306.     
  307.     return docIndex;
  308. }
  309.  
  310. //--------------------------------------------------------------------------------
  311. // TApplication::AccessByUniqueID
  312. //--------------------------------------------------------------------------------
  313. TAbstractScriptableObject* TApplication::AccessByUniqueID(const TAETransaction& t, DescType desiredClass, TDescriptor uniqueID)
  314. {
  315.     TAbstractScriptableObject* result = nil;
  316.     
  317.     if(desiredClass == cDocument)
  318.     {
  319.         result = this->FindDocument(uniqueID.GetSInt64Data(), true);
  320.     }
  321.     else
  322.         result = Inherited::AccessByUniqueID(t, desiredClass, uniqueID);
  323.  
  324.     return result;
  325. } // TApplication::AccessByUniqueID
  326.  
  327. //--------------------------------------------------------------------------------
  328. // TApplication::GetProperty
  329. //--------------------------------------------------------------------------------
  330. TDescriptor TApplication::GetProperty(const TAETransaction& t, DescType propertyName, DescType desiredType, unsigned long additionalInfo)
  331. {
  332.     TDescriptor result;
  333.     
  334.     switch(propertyName)
  335.     {
  336.         case pName:
  337.         {
  338. #if 0
  339.             //
  340.             // •••Need to ask the process manager what our name is
  341.             //
  342.             result.MakeString("\pdb+");
  343. #endif
  344.             break;
  345.         }
  346.         
  347.         //
  348.         // This is the resolution mode:  use "color" temporarily
  349.         //
  350.         case pColor:
  351.         {
  352.             result.SetSInt32Data(fResolutionMode);
  353.             break;
  354.         }
  355.         
  356.         default:
  357.         {
  358.             result = Inherited::GetProperty(t, propertyName, desiredType, additionalInfo);
  359.         }
  360.     }
  361.     
  362.     return result;
  363. }
  364.  
  365. //--------------------------------------------------------------------------------
  366. // TApplication::SetProperty
  367. //--------------------------------------------------------------------------------
  368. void TApplication::SetProperty(const TAETransaction& t, DescType propertyName, TDescriptor& data, unsigned long additionalInfo)
  369. {
  370.     switch(propertyName)
  371.     {
  372.         //
  373.         // This is the resolution mode:  use "color" temporarily
  374.         //
  375.         case pColor:
  376.         {
  377.             this->SetResolutionMode(data.GetSInt32Data());            
  378.             break;
  379.         }
  380.         
  381.         default:
  382.         {
  383.             Inherited::SetProperty(t, propertyName, data, additionalInfo);
  384.         }
  385.     }
  386. }
  387.  
  388. //--------------------------------------------------------------------------------
  389. // TApplication::AECommand
  390. //--------------------------------------------------------------------------------
  391. TDescriptor TApplication::AECommand(const TAETransaction& t, long aeCommandID, TAbstractScriptableObject* auxObjects, long auxInfo)
  392. {
  393.     TDescriptor result;
  394.     TDescriptor intermediate;
  395.     
  396.     switch(aeCommandID)
  397.     {
  398.         case kAEOpen:
  399.         {
  400.             TDescriptor openSpecDesc = t.Message().GetDescriptorParameter(keyDirectObject);
  401.             for(TDescriptorIterator iter(openSpecDesc); iter.More(); iter.Next())
  402.             {
  403.                 TFSSpecification openFSSpec(iter.Current());
  404.                 
  405.                 TAbstractDocument* document = this->FindDocument(openFSSpec, true);
  406.                 if(document != nil)
  407.                 {
  408.                     intermediate = document->BuildObjectSpecifier(t);
  409.                     result.AppendListAndDispose(intermediate);
  410.                 }
  411.             }
  412.             openSpecDesc.Dispose();
  413.             break;
  414.         }
  415.         
  416.         default:
  417.         {
  418.             result = Inherited::AECommand(t, aeCommandID, auxObjects, auxInfo);
  419.             break;
  420.         }
  421.     }
  422.     
  423.     return result;
  424. }
  425.  
  426. //--------------------------------------------------------------------------------
  427. // TApplication::CreateNewElement
  428. //--------------------------------------------------------------------------------
  429. TAbstractScriptableObject* TApplication::CreateNewElement(const TAETransaction& t, DescType newObjectClass, TDescriptor initialData, TDescriptor initialProperties, Boolean& usedInitialData, Boolean& usedInitialProperties)
  430. {
  431.     TAbstractScriptableObject* result = nil;
  432.     
  433.     //
  434.     // The application can only create documents
  435.     //
  436.     if(newObjectClass == cDocument)
  437.     {
  438.         //
  439.         // If we create a new document, it will automatically
  440.         // be added to the global documents list
  441.         //
  442.         result = TScriptableDBDocument::NewDatabase();
  443.     }
  444.     else
  445.         result = Inherited::CreateNewElement(t, newObjectClass, initialData, initialProperties, usedInitialData, usedInitialProperties);
  446.  
  447.     return result;
  448. }
  449.  
  450. //--------------------------------------------------------------------------------
  451. // TApplication::SetResolutionMode
  452. //--------------------------------------------------------------------------------
  453. void TApplication::SetResolutionMode(long newValue)
  454. {
  455.     switch(newValue)
  456.     {
  457.         //
  458.         // Don't do anything special, not even marking
  459.         // (NOTE:  In this mode, object specifier resolutions
  460.         // that have more than one result will not work, as
  461.         // we do not have code that deals with AE-lists-of-tokens)
  462.         //
  463.         case 0:
  464.             TDescriptor::SetCallbackFlags(kAEIDoMinimum);
  465.             InstallPreResolveProc(nil);
  466.             break;
  467.         
  468.         //
  469.         // Let the OSL resolve all specifiers, including whose clauses
  470.         //
  471.         case 1:
  472.             TDescriptor::SetCallbackFlags(kAEIDoMarking);
  473.             InstallPreResolveProc(nil);
  474.             break;
  475.         
  476.         //
  477.         // OSL does most resolution, but we do whose clauses
  478.         //
  479.         case 2:
  480.             TDescriptor::SetCallbackFlags(kAEIDoMarking + kAEIDoWhose);
  481.             InstallPreResolveProc(nil);
  482.             break;
  483.         
  484.         //
  485.         // We do all object specifier resolution without ever calling OSL
  486.         // (but set the callback flags anyway, just in case).
  487.         //
  488.         case 3:
  489.             TDescriptor::SetCallbackFlags(kAEIDoMarking + kAEIDoWhose);
  490.             InstallPreResolveProc(ResolveObjectSpecifier);
  491.             break;
  492.         
  493.         default:
  494.             newValue = fResolutionMode;
  495.             break;
  496.     }
  497.     fResolutionMode = newValue;
  498. }
  499.  
  500.